package xyz.xtt.exchange.service.impl;

import static java.util.stream.Collectors.joining;

import java.util.ArrayList;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.google.common.collect.Lists;
import com.google.common.primitives.Longs;
import com.tongtong.share.params.AuditRequest;
import com.tongtong.share.response.AuditResponse;
import com.tongtong.share.response.AuditThirdResponse;
import com.tongtong.share.vo.AuditTypeEnum;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import xyz.xtt.exchange.constants.CheckLimitTypeEnum;
import xyz.xtt.exchange.entity.TblAuditLog;
import xyz.xtt.exchange.service.IInnerService;
import xyz.xtt.exchange.service.ITblAuditLogService;
import xyz.xtt.exchange.service.ThirdService;
import xyz.xtt.exchange.vo.AuditCheckResult;

/**
 * @author huqibo
 * @date 2024/11/20
 */
@RefreshScope
@Slf4j
@Service
public class ThirdServiceImpl implements ThirdService {
	private static final String JOIN_STR = "/";
	ExecutorService executorService = Executors.newFixedThreadPool(2);
	private static final String THIRD_TYPE = "tx";
	private static final String TRUE = "true";
	@Autowired
	private IInnerService iInnerService;

	@Value("${asset.openTextAudit:true}")
	private Boolean openTextAudit;

	@Value("${asset.openImageAudit:true}")
	private Boolean openImageAudit;
	@Autowired
	private ITblAuditLogService iTblAuditLogService;
	@Autowired
	private PlatformTransactionManager transactionManager;

//	@Transactional(propagation = Propagation.REQUIRES_NEW)
	@Override
	public void saveAudit(String text, String uid, int auditType, Boolean textCheckResult, AuditResponse textAudit, CheckLimitTypeEnum limitType, String label,
			Long requestId) {
		// 创建一个新的事务定义
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		TransactionStatus status = transactionManager.getTransaction(def); // 开始新的事务
		try {
			TblAuditLog build = TblAuditLog
					.builder()
					.id(IdUtil.getSnowflakeNextId())
					.auditType(auditType)
					.appUserId(Longs.tryParse(uid))
					.contxt(text)
					.thirdType(THIRD_TYPE)
					.result(Objects.equals(Boolean.TRUE, textCheckResult) ? 1 : 0)
					.thirdResult(JSONUtil.toJsonStr(textAudit))
					.crtTime(System.currentTimeMillis())
					.bizType(limitType.name())
					.requestId(requestId)
					.label(label)
					.build();
			iTblAuditLogService.save(build);// 提交事务
			transactionManager.commit(status);
		} catch (Exception e) {
			log.info("buildSave ex: {}", e.getMessage(), e);
			transactionManager.rollback(status);
		}
	}

	@Override
	public AuditCheckResult audit(String text, String imgUrl, String uid, CheckLimitTypeEnum limitType) {
		long requestId = IdUtil.getSnowflakeNextId();
		AuditCheckResult checkResult = AuditCheckResult.builder().build();
		if (Objects.equals(openImageAudit, Boolean.TRUE) && StringUtils.isNotBlank(imgUrl)) {
			AuditResponse txAuditing = iInnerService.txAuditing(imgUrl);
			log.info("middlewareClient.txAuditing response: {}", JSONUtil.toJsonStr(txAuditing));
			Boolean imgCheckResult = checkResult(txAuditing);
			String label = label(txAuditing);
			CompletableFuture.runAsync(() -> saveAudit(imgUrl, uid, 1, imgCheckResult, txAuditing, limitType, label, requestId), executorService);
			checkResult.setImgResponse(txAuditing);
			checkResult.setImgResult(imgCheckResult);
			if (!imgCheckResult) {
				return checkResult;
			}
		}
		if (Objects.equals(openTextAudit, Boolean.TRUE) && StringUtils.isNotBlank(text)) {
			AuditRequest auditRequest = AuditRequest.builder().type(AuditTypeEnum.TEXT_CONTENT).target(text).build();
			AuditResponse textAudit = iInnerService.textAudit(auditRequest);
			log.info("middlewareClient.textAudit response: {}", JSONUtil.toJsonStr(textAudit));
			Boolean textCheckResult = checkResult(textAudit);
			String label = label(textAudit);
			CompletableFuture.runAsync(() -> saveAudit(text, uid, 0, textCheckResult, textAudit, limitType, label, requestId), executorService);
			checkResult.setTxtResponse(textAudit);
			checkResult.setTxtResult(textCheckResult);
			if (!textCheckResult) {
				return checkResult;
			}
		}
		return checkResult;
	}

	private Boolean checkResult(AuditResponse textAudit) {
		return Optional.ofNullable(textAudit).map(AuditResponse::isCheck).orElse(Boolean.FALSE);
	}

	/**
	 * 取出label和subLab
	 * 
	 * @param textAudit
	 * @return
	 */
	private static String label(AuditResponse textAudit) {
		Optional<AuditThirdResponse> map = Optional.ofNullable(textAudit).filter(Objects::nonNull).map(x -> x.getThirdRespose());
		ArrayList<Optional<String>> labelList = Lists.newArrayList(map.map(x -> x.getLabel()), map.map(x -> x.getSubLabel()));
		return labelList.stream().filter(Optional::isPresent).map(Optional::get).filter(StringUtils::isNotBlank).collect(joining(JOIN_STR));
	}

}
